#pragma once
#include "CWindow/CWindowBase.h"
#include "Tools/CBitmapDraw.h"
#include <vector>

#define FRAME_UPDATE_TIMER_ID           (0x200)
#define FRAME_UPDATE_TIME               (20)

#define PLAYER_ACTION_TIMER_ID          (0x201)
#define PLAYER_ACTION_TIME              (50)

#define ENEMY_ACTION_TIMER_ID           (0x202)
#define ENEMY_ACTION_TIME               (100)

#define BULLET_ACTION_TIMER_ID          (0x203)
#define BULLET_ACTION_TIME              (20)

#define BULLET_CLEAR_TIMER_ID           (0x204)
#define BULLET_CLEAR_TIME               (1000)

#define MAIN_FRAME_GRID_SIZE            (8)

#define MAIN_FRAME_X_GRID_COUNT         (1024 / MAIN_FRAME_GRID_SIZE)
#define MAIN_FRAME_Y_GRID_COUNT         (768 / MAIN_FRAME_GRID_SIZE)

#define MAIN_FRAME_WIDTH                (MAIN_FRAME_X_GRID_COUNT * MAIN_FRAME_GRID_SIZE)
#define MAIN_FRAME_HEIGHT               (MAIN_FRAME_Y_GRID_COUNT * MAIN_FRAME_GRID_SIZE)

#define FIELD_POS_Y                     (6)
#define STAGE_LEVEL_MAX                 (11)
#define PLAYER_X_COUNT                  (1)
#define PLAYER_Y_COUNT                  (1)

#define ENEMY_HITTING_TIME              (8)
#define PLAYER_HITTING_TIME             (8)

const DWORD DRAW_BACK_GRID_COLOR = RGB(255, 255, 255);
const DWORD DRAW_EMPTY_COLOR = RGB(255, 255, 255);

const DWORD DRAW_ENEMY_COLOR = RGB(0, 0, 0);
const DWORD DRAW_ENEMY_BULLET_COLOR = RGB(255, 0, 0);

const DWORD DRAW_PLAYER_COLOR = RGB(0, 0, 0);
const DWORD DRAW_PLAYER_BULLET_COLOR = RGB(0, 255, 0);

const DWORD DRAW_GAME_OVER_COLOR = RGB(255, 0, 255);

const DWORD DRAW_BLACK_COLOR = RGB(0, 0, 0);

const DWORD DRAW_BLOOD_BKG_COLOR = RGB(255, 0, 0);
const DWORD DRAW_BLOOD_COLOR = RGB(0, 255, 0);

const DWORD DRAW_ENEMY_HITTING_COLOR = RGB(255, 0, 0);
const DWORD DRAW_PLAYER_HITTING_COLOR = RGB(255, 255, 0);

enum MoveActionType
{
    MAT_None = 0,
    MAT_Left = 1,
    MAT_Right = 2,
    MAT_Up = 4,
    MAT_Down = 8,
    MAT_Died = 16,
};

typedef struct _BULLET_INFO
{
    _BULLET_INFO()
    {
        this->pt = {0};
        this->action = MoveActionType::MAT_None;
    }

    _BULLET_INFO(POINT pt, DWORD action = MoveActionType::MAT_Up)
    {
        this->pt = pt;
        this->action = action;
    }

    POINT pt;
    DWORD action;
    LONG  blood = 1;
    LONG  bloodTotal = 1;
}BULLET_INFO;

typedef struct _CHARACTERS_INFO
{
    _CHARACTERS_INFO()
    {
        this->pt = { 0 };
        this->action = MoveActionType::MAT_None;
    }

    _CHARACTERS_INFO(POINT pt, DWORD action = MoveActionType::MAT_Down)
    {
        this->pt = pt;
        this->action = action;
    }

    POINT pt = {0,0};
    DWORD action = MoveActionType::MAT_Up;
    DWORD lastAction = MoveActionType::MAT_Up;
    DWORD moveCount = 0;
    DWORD fireCount = 0;
    LONG  blood = 1;
    LONG  bloodTotal = 1;
    LONG  hitting = 0;
}CHARACTERS_INFO;

class CMainFrame: 
    public CWindowBase
{
public:

    CMainFrame();
    CMainFrame(const CMainFrame& r) = delete;
    ~CMainFrame();

    HDC GetMemDC();
    HDC GetBackMemDC();
    HBITMAP GetBitmap();
    HBITMAP GetBackBitmap();

protected:
    wnd_msg LRESULT OnCreate(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnClose(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnEraseBkgnd(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnMouseActivate(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnNcHittest(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnKeyDown(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnKeyUp(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnMButtonDown(WPARAM wParam, LPARAM lParam);

    wnd_msg LRESULT OnMenuExit(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnShowGrid(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnPreStage(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnNextStage(WPARAM wParam, LPARAM lParam);
    wnd_msg LRESULT OnResetStage(WPARAM wParam, LPARAM lParam);
private:

    void DrawFrame(CBitmapDraw& draw);
    void DrawBkgGrid(CBitmapDraw& draw);
    void DrawGameCharacters(CBitmapDraw& draw, const CHARACTERS_INFO& enemy, DWORD dwColor = DRAW_PLAYER_COLOR, bool bEnery = true);
    void DrawBlood(CBitmapDraw& draw, const CHARACTERS_INFO& enemy);
    void DrawPlayer(CBitmapDraw& draw);
    void DrawEnemy(CBitmapDraw& draw);
    void DrawBullets(CBitmapDraw& draw, const BULLET_INFO& item, DWORD dwColor);
    void DrawBullets(CBitmapDraw& draw);
    void DrawGameState(CBitmapDraw& draw);
    void PlayerAction();
    void EnemyAction();
    void BulletsAction();
    void ClearBullets();
    void InitEnemy(int nCount = 1);
    void InitPlayer();
    void BulletHitting();
    void BulletsHit();
    bool BulletHit(const CHARACTERS_INFO& enemy, const BULLET_INFO& bullet, bool bPlayer);
    void PreStage();
    void NextStage();
    void ResetStage();

    DECLARE_WND_MESSAGE_MAP()

private:

    HDC         m_hMemDC = NULL;
    HBITMAP     m_hMemBitmap = NULL;
    HDC         m_hBackMemDC = NULL;
    HBITMAP     m_hBackMemBitmap = NULL;
    HFONT       m_hFont = NULL;
    CBitmapDraw m_draw;

    bool        m_Fire = false;
    bool        m_Pause = false;
    bool        m_GameOver = true;
    bool        m_FirstPlay = true;
    bool        m_ShowGrid = false;

    int         m_EnemyLevel = 1;
    int         m_WeaponLevel = 1;
    int         m_FailedCount = 0;
    int         m_KilledCount = 0;
    int         m_StageCount = 0;
    int         m_EnemyCount = 0;

    std::vector<CHARACTERS_INFO> m_enemyList;
    std::vector<BULLET_INFO> m_playerBullets;
    std::vector<BULLET_INFO> m_enemyBullets;
    CHARACTERS_INFO m_Player;
};